/**
 * Copyright (c) 2009-2011, chunquedong(YangJiandong)
 * 
 * This file is part of ChunMap project
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE(Version >=3)
 * 
 * History:
 *     2010-05-05  Jed Young  Creation
 */
package chunmap.model.coord;

import chunmap.util.math.MyDouble;

/**
 * @author chunquedong
 * 
 */
public class Coordinate3D implements Position {

	private final Coordinate2D coordinate2D;
	private final double z;

	public Coordinate3D(double x, double y, double z) {
		coordinate2D = new Coordinate2D(x, y);
		this.z = z;
	}

	public Coordinate3D(Coordinate2D coordinate2D, double z) {
		this.coordinate2D = coordinate2D;
		this.z = z;
	}

	public double getX() {
		return coordinate2D.getX();
	}

	public double getY() {
		return coordinate2D.getY();
	}

	public double getZ() {
		return z;
	}

	public boolean is3D() {
		return true;
	}

	public Coordinate2D toCoordinate2D() {
		return coordinate2D;
	}
	
	@Override
	public double distance2D(Position other) {
		double x1 = getX();
		double y1 = getY();
		double x2 = other.getX();
		double y2 = other.getY();

		double d1 = Math.pow((x1 - x2), 2.0);
		double d2 = Math.pow((y1 - y2), 2.0);

		double dis = Math.sqrt(d1 + d2);
		return dis;
	}

	@Override
	public boolean approximateEquals(Position aother) {
		if (this == aother)
			return true;
		if (aother == null)
			return false;
		if (getClass() != aother.getClass())
			return false;

		Coordinate3D other = (Coordinate3D) aother;

		if (!(coordinate2D.approximateEquals(other.coordinate2D))) {
			return false;
		}
		return MyDouble.approximateEquals(z, other.getZ());
	}

	// ------------------------------------------------------------

	@Override
	public String toString() {
		return "Coordinate [x=" + coordinate2D.getX() + ", y="
				+ coordinate2D.getY() + ", z=" + z + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((coordinate2D == null) ? 0 : coordinate2D.hashCode());
		long temp;
		temp = Double.doubleToLongBits(z);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Coordinate3D other = (Coordinate3D) obj;
		if (coordinate2D == null) {
			if (other.coordinate2D != null)
				return false;
		} else if (!coordinate2D.equals(other.coordinate2D))
			return false;
		if (Double.doubleToLongBits(z) != Double.doubleToLongBits(other.z))
			return false;
		return true;
	}
	
	public int compareTo(Position other)
    {
        if (getX() < other.getX())
            return -1;
        if (getX() > other.getX())
            return 1;
        if (getY() < other.getY())
            return -1;
        if (getY() > other.getY())
            return 1;
        if (z < other.getZ())
            return -1;
        if (z > other.getZ())
            return 1;
        return 0;
    }

	@Override
	public Object clone() {
		return new Coordinate3D(coordinate2D.getX(), coordinate2D.getY(), z);
	}
}